

`include "defines.v"



module RX_DATA_CHANGE

(
    rst,
    clk,
    rd_clk,
    
    hdlc_frm_data,
    hdlc_frm_sop_ind,
    hdlc_frm_eop_ind,
    hdlc_frm_abort_ind,
    hdlc_frm_dat_vld,
    
    data_rdy,
    rd_en,
    data_out,
    data_full
    
   
    );
    
// *************************
// INPUTS and OUPUTS
// *************************

input          rst;
input          clk;
input          rd_clk;

input[63:0]    hdlc_frm_data;
input[7:0]     hdlc_frm_sop_ind;
input[7:0]     hdlc_frm_eop_ind;
input[7:0]     hdlc_frm_abort_ind;
input          hdlc_frm_dat_vld;


output         data_rdy/* synthesis syn_keep = 1 */;
input          rd_en;
output[175:0]  data_out/* synthesis syn_keep = 1 */;
output         data_full/* synthesis syn_keep = 1 */;

//reg				data_rdy;



// *************************
// INTERNAL SIGNALS
// *************************
wire[2:0]      sop_sum;
wire[2:0]      eop_sum;
reg[2:0]       sop_sum_d1;
reg[2:0]       eop_sum_d1;
reg[2:0]       fr_cnt;
reg            dat_vld_d1;
reg[63:0]      dat_d1;
reg[7:0]       sop_d1;
reg[7:0]       eop_d1;
reg[7:0]       abort_d1;
reg[127:0]     data_reg;
reg[15:0]      sop_reg;
reg[15:0]      eop_reg;
reg[15:0]      abort_reg;
reg[1:0]       cnt;

reg[127:0]     change_dat;
reg[15:0]      change_sop;
reg[15:0]      change_eop;
reg[15:0]      change_abort;
reg            change_vld;

// *************************
// CODE
// *************************





assign sop_sum =    hdlc_frm_sop_ind[0] + hdlc_frm_sop_ind[1] + hdlc_frm_sop_ind[2] + hdlc_frm_sop_ind[3]
                  + hdlc_frm_sop_ind[4] + hdlc_frm_sop_ind[5] + hdlc_frm_sop_ind[6] + hdlc_frm_sop_ind[7];
                  
assign eop_sum =    hdlc_frm_eop_ind[0] + hdlc_frm_eop_ind[1] + hdlc_frm_eop_ind[2] + hdlc_frm_eop_ind[3]
                  + hdlc_frm_eop_ind[4] + hdlc_frm_eop_ind[5] + hdlc_frm_eop_ind[6] + hdlc_frm_eop_ind[7];


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
    begin
        sop_sum_d1 <= 3'b0;
        eop_sum_d1 <= 3'b0;
        dat_vld_d1 <= 1'b0;
        dat_d1 <= 64'b0;
        sop_d1 <= 8'b0;
        eop_d1 <= 8'b0;
        abort_d1 <= 8'b0;
    end
    else
    begin
        sop_sum_d1 <= sop_sum;
        eop_sum_d1 <= eop_sum;
        dat_vld_d1 <= hdlc_frm_dat_vld;
        dat_d1 <= hdlc_frm_data;
        sop_d1 <= hdlc_frm_sop_ind;
        eop_d1 <= hdlc_frm_eop_ind;
        abort_d1 <= hdlc_frm_abort_ind;
    end
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        fr_cnt <= 3'b0;
    else if(dat_vld_d1 == 1)
        fr_cnt <= fr_cnt + sop_sum_d1 - eop_sum_d1;
end


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        data_reg <= 128'b0;
    else if(dat_vld_d1 == 1)
        data_reg <= {data_reg[63:0],dat_d1};
    else if(dat_vld_d1 == 0 && fr_cnt == 0 && cnt == 1)
        data_reg <= {data_reg[63:0],64'b0};
end


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        sop_reg <= 16'b0;
    else if(dat_vld_d1 == 1)
        sop_reg <= {sop_reg[7:0],sop_d1};
    else if(dat_vld_d1 == 0 && fr_cnt == 0 && cnt == 1)
        sop_reg <= {sop_reg[7:0],8'b0};
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        eop_reg <= 16'b0;
    else if(dat_vld_d1 == 1)
        eop_reg <= {eop_reg[7:0],eop_d1};
    else if(dat_vld_d1 == 0 && fr_cnt == 0 && cnt == 1)
        eop_reg <= {eop_reg[7:0],8'b0};
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        abort_reg <= 16'b0;
    else if(dat_vld_d1 == 1)
        abort_reg <= {abort_reg[7:0],abort_d1};
    else if(dat_vld_d1 == 0 && fr_cnt == 0 && cnt == 1)
        abort_reg <= {abort_reg[7:0],8'b0};
end


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        cnt <= 2'b0;
    else if(cnt == 2 && dat_vld_d1)
        cnt <= 2'b1;
    else if(cnt == 2)
        cnt <= 2'b0;    
    else if(dat_vld_d1)
        cnt <= cnt + 1;
    else if(dat_vld_d1 == 0 && fr_cnt == 0 && cnt == 1)
        cnt <= cnt + 1;
end


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        change_vld <= 1'b0;
    else if(cnt == 2)
        change_vld <= 1'b1;
    else
        change_vld <= 1'b0;
end


always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        change_dat <= 128'b0;
    else if(cnt == 2)
        change_dat <= data_reg;
    else
        change_dat <= 128'b0;
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        change_sop <= 16'b0;
    else if(cnt == 2)
        change_sop <= sop_reg;
    else
        change_sop <= 16'b0;
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        change_eop <= 16'b0;
    else if(cnt == 2)
        change_eop <= eop_reg;
    else
        change_eop <= 16'b0;
end

always @(posedge clk or `RST_EDGE rst)
begin            
    if(rst == `RST_VALUE)
        change_abort <= 16'b0;
    else if(cnt == 2)
        change_abort <= abort_reg;
    else
        change_abort <= 16'b0;
end



wire              empty;
//wire[12:0]        wr_data_count;
//wire[12:0]        rd_data_count;
wire[11:0]        wr_data_count;
wire[11:0]        rd_data_count;

//asfifo176x8k u_asfifo176x8k
//
//(
//	.rst          (rst),
//	.wr_clk       (clk),
//	.rd_clk       (rd_clk),
//	.din          ({change_sop,change_eop,change_abort,change_dat}),
//	.wr_en        (change_vld),
//	.rd_en        (rd_en),
//	.dout         (data_out),
//	.full         (),
//	.empty        (empty),
//	.rd_data_count(rd_data_count),
//	.wr_data_count(wr_data_count)
//	
//	);


asfifo176x4k u_asfifo176x4k

(
	.rst          (rst),
	.wr_clk       (clk),
	.rd_clk       (rd_clk),
	.din          ({change_sop,change_eop,change_abort,change_dat}),
	.wr_en        (change_vld),
	.rd_en        (rd_en),
	.dout         (data_out),
	.full         (),
	.empty        (empty),
	.rd_data_count(rd_data_count),
	.wr_data_count(wr_data_count)
	
	);

	
	
assign data_rdy = (empty ==0);
//assign data_rdy = (rd_data_count >32);       // change by DDV
//always @(posedge rd_clk or `RST_EDGE rst)      // change by DDV
//begin            
//    if(rst == `RST_VALUE)
//        data_rdy <= 1'b0;
//    else if(rd_data_count[12:0] >= 13'h01f)
//        data_rdy <= 1'b1;
//    else
//        data_rdy <= 1'b0;
//end




//assign data_full = (wr_data_count > 7000);     // for semp request to less ram
assign data_full = (wr_data_count > 3000);



endmodule









